
/***
 * @Description: 本文件主要是定义协议栈的一些工具类的执行函数，包括大小端转换等
 * @Author: Liverpool
 * @Date: 2024-05-19 21:34:20
 * @LastEditTime: 2024-05-19 21:34:39
 * @LastEditors: Liverpool
 */
#include "tools.h"
#include "debug.h"

/***
 * @description: （静态函数）判断当前协议栈的存储方式是否为小端存储
 * @Author: Liverpool
 * @Date: 2024-05-19 22:05:56
 * @return {*} 1:小端存储  0:大端存储
 */
static int is_little_endian(void)
{
    uint16_t value = 0x1234;
    return *(uint8_t *)&value == 0x34;
}

/***
 * @description: 工具模块相关功能的初始化函数
 * @Author: Liverpool
 * @Date: 2024-05-19 21:37:47
 * @return {*} 这个协议栈系统中配置的错误
 */
net_err_t tools_init(void)
{
    debug_info(Debug_Tools, "tools init...");
    // 大小端判断
    if (is_little_endian() != NET_ENDIAN_LITTLE)
    {
        debug_error(Debug_Tools, "check endian failed!");
        return NET_ERR_SYS;
    }
    debug_info(Debug_Tools, "tools init done...");
    return NET_ERR_OK;
}

/***
 * @description: 对16位的数据做校验和相加处理(IP数据报的头部校验处理)
 * @Author: Liverpool
 * @Date: 2024-07-09 18:38:54
 * @return {*} 返回的最后的16位数据值
 * @param {void} *buf 需要校验的数据块的内存地址
 * @param {uint16_t} len 需要校验的数据块的数据长度
 * @param {uint32_t} pre_sum 上一个数据块的校验和的值
 * @param {int} complement 是否需要对计算得到的校验和取反
 */
uint16_t checksum_16(uint32_t offset, void *buf, uint16_t len, uint32_t pre_sum, int complement)
{
    uint16_t *curr_buf = (uint16_t *)buf; // 进行16位数据的转化
    uint32_t checksum = pre_sum;          // 保留上一块的计算值
    if (offset & 0x1)                     // 是奇数
    {
        uint8_t *buf_temp = (uint8_t *)curr_buf;
        checksum += *buf_temp++ << 8; // 奇数需要进行增加
        curr_buf = (uint16_t *)buf_temp;
        len--;
    }
    while (len > 1)
    {
        checksum += *curr_buf;
        curr_buf++;
        len -= 2;
    }
    // 对校验长度为奇数的数据块进行处理
    if (len > 0)
    {
        checksum += *((uint8_t *)curr_buf);
    }
    uint16_t high;
    // 把校验和的高16位加在低16位上，直至变为0
    while ((high = checksum >> 16) != 0)
    {
        checksum = high + (checksum & 0xFFFF);
    }
    // 根据是否取反来返回不同的值
    return complement ? (uint16_t)~checksum : (uint16_t)checksum;
}